package controllers

import (
	"bytes"
	"encoding/base64"
	"encoding/json"
	"fmt"
	"github.com/go-playground/validator/v10"
	"github.com/qit-team/snow-core/redis"
	"io/ioutil"
	"net/http"
	"snow-im/app/constants/errorcode"
	utils2 "snow-im/app/utils"
	"snow-im/app/utils/common"
	"snow-im/config"
	"strconv"

	"github.com/gin-gonic/gin"
)

/**
 * 成功时返回
 */
func Success(c *gin.Context, data interface{}, message string) {
	if message == "" {
		message = errorcode.GetMsg(errorcode.Success, c.GetHeader("local"))
	}
	if config.GetConf().Env == "production" {
		c.String(http.StatusOK, EncriptJson(gin.H{
			"code":    errorcode.Success,
			"message": message,
			"data":    data,
		}))
	} else {
		c.JSON(http.StatusOK, gin.H{
			"code":    errorcode.Success,
			"message": message,
			"data":    data,
		})
	}

	c.Abort()
}
func EncriptJson(h gin.H) string {
	var data, err = json.Marshal(h)
	if err != nil {
		utils2.Log(nil, "encriptJso", err)
	}
	rs, err := common.Des3Encrypt(data, config.GetConf().AppKey)
	res := base64.StdEncoding.EncodeToString(rs)
	return res
}

func SucessBack(c *gin.Context) {
	c.Writer.Write([]byte("ok"))
	c.Abort()
}

/**
 * 失败时返回
 */
func Error(c *gin.Context, code int, msg ...string) {
	message := ""
	if len(msg) > 0 {
		message = msg[0]
	} else {
		message = errorcode.GetMsg(code, "")
	}
	if config.GetConf().Env == "production" {
		c.String(http.StatusOK, EncriptJson(gin.H{
			"code":    code,
			"message": message,
			"data":    make(map[string]string),
		}))
	} else {
		c.JSON(http.StatusOK, gin.H{
			"code":    code,
			"message": message,
			"data":    make(map[string]string),
		})
	}

	c.Abort()
}

func Error404(c *gin.Context) {
	Error(c, errorcode.NotFound, "路由不存在")
}

func Error500(c *gin.Context) {
	Error(c, errorcode.SystemError)
}

type HTTPError struct {
	Code    int    `json:"code" example:"400"`
	Message string `json:"message" example:"status bad request"`
}

/**
 * 将请求的body转换为request数据结构
 * @param c
 * @param request  传入request数据结构的指针 如 new(TestRequest)
 */
func GenRequest(c *gin.Context, request interface{}, toDo func(), param ...interface{}) (err error) {
	body, err := ReadBody(c)
	if err != nil {
		return
	}
	fmt.Println(string(body), "req")
	if config.GetConf().Env == "production" && param == nil {
		body, _ = base64.StdEncoding.DecodeString(string(body))
		body, err = common.Des3ECBDecrypt(body, config.GetConf().AppKey)
	}
	if err != nil {
		utils2.Log(nil, "encrypt", err)
	}
	err = json.Unmarshal(body, request)
	utils2.Log(nil, "json", string(body))
	if err == nil {
		validate := validator.New()
		errValidate := validate.Struct(request)
		utils2.Log(nil, "validate", errValidate)
		if errValidate != nil {
			utils2.Log(c, "param_validator_exception:"+c.Request.URL.Path, errValidate)
			return errValidate
		}
		toDo()
	} else {
		utils2.Log(c, "param err", err)
		Error(c, errorcode.ParamError, errorcode.GetMsg(errorcode.ParamError, c.GetHeader("local")))
	}
	return err
}

// 重复读取body
func ReadBody(c *gin.Context) (body []byte, err error) {
	body, err = ioutil.ReadAll(c.Request.Body)
	if err != nil {
		return
	}
	c.Request.Body = ioutil.NopCloser(bytes.NewBuffer(body))
	return
}

func HandRes(c *gin.Context, data interface{}, err error) {
	if err == nil {
		Success(c, data, "")
	} else {
		Error(c, errorcode.SystemError, err.Error())
	}
}
func HandCodeRes(c *gin.Context, data interface{}, code int) {
	if code == errorcode.Success {
		Success(c, data, errorcode.GetMsg(code, ""))
	} else {
		Error(c, code, errorcode.GetMsg(code, ""))
	}
}
func GetPlayerId(c *gin.Context) int64 {
	playerId, _ := c.Get("playerId")
	if playerId == nil {
		return 0
	}
	playerIdInt, _ := strconv.ParseInt(playerId.(string), 10, 64)
	return playerIdInt
}

func Frequence(key string) bool {
	if rs, _ := redis.GetRedis().Exists(utils2.GetRealKey(key)); rs > 0 {
		return false
	} else {
		redis.GetRedis().SetEX(utils2.GetRealKey(key), 1, 5)
		return true
	}

}
